#pragma once
#include "NameNode.grpc.pb.h"
#include <grpcpp/grpcpp.h>
#include <memory>
#include<algorithm>
#include <iostream>
#include<string>
#include"NameNode.h"
#include"common.h"
using namespace grpc;
//本机
ServiceImpl::ServiceImpl()
{
   for(int i=8083;i<8200;i++)
   {
      vport.push_back(i);
   }
   GF=new new GetFiles("/");
   FileTree= new GetFiles();
}
ServiceImpl::~ServiceImpl()
{
   delete GF;
   delete FileTree;
}
int ihash(string s)
{
   uint64_t ret=0;
   for(auto& x:s)
   {
      ret=ret*31+x-'a';
   }
   return ret&0x7fffffff;

}

Node* ServiceImpl::GetNode(string filepath)
{
   //if返回空则没找到
   _mtx.lock();

   //GF->Get_FileMetadata("/A/B",node);
   FileTree node;
   if(GF->Get_FileMetadata(filepath,node)==false)
   {
      //没找到
       std::cout<<"没找到node"<<std::endl;
       _mtx.unlock();
       return nullptr;
   }
   _mtx.unlock();
   return &node;
}

Status ServiceImpl::FindAddr(grpc::ServerContext*  context,const Rpc::FindAddrRequest* request,Rpc::FindAddrReply* response)
{
   std::string filepath=request->filepath();
    FileTree* node=GetNode(filepath);
   if(node==nullptr)
   {
      return Status(NOT_FOUND,"没有找到文件");
   }

   auto chunk_handles=node->chunk_handles;
   for(int i=0;i<map.size();i++)
   {
      auto chunk_handle=chunk_handles[i];
      auto& chunk=_chunks[chunk_handle];//chunk*

      response->add_chunk_handles(chunk_handle);
      response->add_addrs(chunk->location[0].location);
   }
   return Status::OK;
}

//上传文件 PUT 文件
 Status ServiceImpl::GetWriteAddr(grpc::ServerContext*  context,const Rpc::GetWriteAddrRequest* request,Rpc::GetWriteAddrReply* response)
 {
    std::string filepath =request->remote_file_path();
    FileTree* node=GetNode(filepath);
    if(node!=nullptr)
    {
      return Status(ALREADY_EXISTS,"文件已经存在")
    }

    int64_t write_size=request->write_data_size;
    _mtx.lock();
    std::string filename=GetFileName(filepath);

    auto& file=FileTree(filename,filepath,write_size,0);
     GF->Add_Path(filepath,file);
    auto& chandle=node->chunk_handles;
    //64M
    for(int i=0;write_size>0;i++)
    {
        auto size=min(write_size,CHUNK_SIZE);
        chandle[i]=hanlde;
        auto& c=new chunk();//chunk
        c->chunk_size=size;
        string host="localhost:"+to_string(ihash(filepath+i)%vport.size());
        c->location->location=host;
         _chunks[chandle[i]]=c;
         write_size-=size;
         response->add_chunk_handles(handle);
         response->add_addrs(host);
         hanlde++;
    }
     _mtx.unlock();
    return Status::OK;
 }

Status ServiceImpl::Stat(grpc::ServerContext*  context,const Rpc::StatRequest* request,Rpc::StatReply* response)
{
   std::string filename=request->filepath();
   FileTree* node=GetNode(filepath);
   if(node==nullptr)
   {
      response->set_existed(false);
      return Status(NOT_FOUND,"没有找到文件");
   }
   
   response->set_existed(true);
   response->set_file_path(node->file_name);
   response->set_file_size(node->size);
   return Status::OK;
}
Status Rename(grpc::ServerContext*  context,const Rpc::RenameRequest* request,Rpc::RenameReply* response)
{
   auto dest=request->des_path();
   auto src=request->src_path();
   FileTree* node=GetNode(filepath);

   if(node==nullptr)
   {
       return Status(NOT_FOUND,"没有找到文件");
   }
   //rename
   if(GF->Rename_Path(src,dest)==false)
   {
       return Status(NOT_FOUND,"RENAME失败");
   }

   return Status::OK;
}
Status Delete(grpc::ServerContext*  context,const Rpc::DeleteRequest* request,Rpc::DeleteReply* response)
{
   auto filepath=request->remote_file_path();
   if(GF->Del_Path(filepath)==false)
   {
      return  Status(NOT_FOUND,"没有找到删除的文件");
   }
   return Status::OK;
}

Status Mkdir(grpc::ServerContext*  context,const Rpc::MkdirRequest* request,Rpc::MkdirReply* response)
{
   auto& path=request->new_file_path();
   //目录不用创建chunk

   if(GF->Add_Path(path,FileTree(GetFileName(path),path,1,1))==false)
   {
      return Status(ALREADY_EXISTS,"已经有该目录了");
   }
   return Status::OK;
}
//list
Status GetSubDirNames(grpc::ServerContext*  context,const Rpc::GetSubDirNamesRequest* request,Rpc::GetSubDirNamesReply* response)
{
   // /A  /B
   auto dirpath=request->file_path();
   FileTree* node=GetNode(dirpath);

   if(node==nullptr)
   {
       return Status(NOT_FOUND,"没有找到目录");
   }
   std::vector<FileTree> ret=GF->Get_Metadata(dirpath);
   for(auto& x:ret)
   {
       response->add_subdir_file_names(x.file_name);
   }
   //返回信息
   return Status::OK;
}
void loop(void* m)
 {
   // 服务构建器，用于构建同步或者异步服务
 
   grpc::ServerBuilder builder;
   // 添加监听的地址和端口，后一个参数用于设置认证方式，这里选择不认证
   builder.AddListeningPort("0.0.0.0:33333",grpc::InsecureServerCredentials());
  // 创建服务对象
   ServiceImpl service;
  // 注册服务
   builder.RegisterService(&service);
  // 构建服务器
   std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
    
   std::cout<<"Server Runing"<<std::endl;
   // 进入服务处理循环（必须在某处调用server->Shutdown()才会返回）
   server->Wait();
   
 }              